package ru.housewife.service.dishes;

import org.hibernate.Session;
import ru.common.hibernate.HibernateAction;
import ru.housewife.form.CookingDishComponentForm;
import ru.housewife.form.CookingDishRecipeForm;
import ru.housewife.form.EatingMenuForm;
import ru.housewife.form.UserForm;
import ru.housewife.model.*;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * modifies cooking dish recipe
 *
 * @author Alexander Troshanin
 */
public class ModifyCookingDishRecipe implements HibernateAction<CookingDishRecipe> {

    private CookingDishRecipeForm recipeForm;
    private UserForm userForm;
    private EatingMenuForm eatingMenu;

    public ModifyCookingDishRecipe(EatingMenuForm eatingMenu, UserForm userForm, CookingDishRecipeForm recipeForm) {
        this.userForm = userForm;
        this.eatingMenu = eatingMenu;
        this.recipeForm = recipeForm;
    }

    @Override
    public CookingDishRecipe execute(Session session) {
        CookingDishRecipe recipe = (CookingDishRecipe) session.get(CookingDishRecipe.class, recipeForm.getId());
        if (recipe == null) {
            return null;
        }

        if (recipe.isCommonRecipe()) {
            // todo: clone this recipe and...
            // NOTE that this recipe may be user's recipe - he tries to edit his own recipe
        } else if (recipe.getOwner() != null && recipe.getOwner().getId() == userForm.getId()) {
            // double check that this is user's recipe
            recipe.setName(recipeForm.getName());
            recipe.setWayToPrepare(recipeForm.getWayToPrepare());
            if (recipe.getRecipesGroup().getId() != recipeForm.getGroup().getId()) {
                recipe.setRecipesGroup((CookingDishRecipeGroup) session.get(CookingDishRecipeGroup.class, recipeForm.getGroup().getId()));
            }

            Map<Long, CookingDishComponentForm> componentsMap = new HashMap<Long, CookingDishComponentForm>();
            for (CookingDishComponentForm cmpForm : recipeForm.getComponents()) {
                componentsMap.put(cmpForm.getId(), cmpForm);
            }

            List<CookingDishComponent> components = recipe.getComponents();
            for (Iterator<CookingDishComponent> iter = components.iterator(); iter.hasNext();) {
                CookingDishComponent component = iter.next();
                CookingDishComponentForm updatedComponent = componentsMap.get(component.getId());
                if (updatedComponent != null) {
                    // update component in DB if there are changes
                    boolean hasChanges = false;
                    if (component.getCount() != updatedComponent.getCount()) {
                        component.setCount(updatedComponent.getCount());
                        hasChanges = true;
                    }
                    if (component.getMeasure() != updatedComponent.getMeasure()) {
                        component.setMeasure(updatedComponent.getMeasure());
                        hasChanges = true;
                    }
                    if (component.getIngredient().getId() != updatedComponent.getIngredient().getId()) {
                        Ingredient ingredient = (Ingredient) session.get(Ingredient.class, updatedComponent.getIngredient().getId());
                        if (ingredient != null) {
                            component.setIngredient(ingredient);
                            hasChanges = true;
                        }
                    }
                    if (component.getPreferableWare().getId() != updatedComponent.getPreferableWare().getId()) {
                        Ware w = (Ware) session.get(Ware.class, updatedComponent.getPreferableWare().getId());
                        if (w != null) {
                            component.setPreferableWare(w);
                            hasChanges = true;
                        }
                    }
                    if (hasChanges) {
                        session.save(component);
                    }

                    componentsMap.remove(component.getId());
                } else {
                    // remove this component
                    iter.remove();
                }
            }

            // add new components - they are in componentsMap
            DishHiberUtils.addNewComponentsToRecipe(session, recipe, componentsMap.values());

            session.save(recipe);

            CookingDishRecipeForm userRecipeForm = userForm.getUsersCookingDishRecipeForm(recipe.getId());
            userForm.removeRecipesWaresFromUsersWares(userRecipeForm);
            userRecipeForm.init(recipe);
            userForm.addRecipesWaresToUsersWares(userRecipeForm);
        } else {
            // todo: clone this recipe and...
            //session.createQuery("select count(x) from EatingMenuDishRecipe x where x.recipe.id=:recipeId and x.eatingMenu.dayMenu.usersTable.user.id=:userId");
        }

        return recipe;
    }
}
